/**
 * @author Shine Chen
 * @date 2011.10.28
 */

package org.mini.core
{
	import com.shine.core.ClassFactory;
	import com.shine.crypt.EventDispatcherBase;
	import com.shine.loader.ClassLoader;
	import com.shine.loader.ILoader;
	import com.shine.loader.LoadFileUtil;
	import com.shine.utils.StringUtil;
	import com.shine.utils.XMLUtil;
	
	import flash.events.Event;
	import flash.utils.Dictionary;
	
	import org.mini.config.AppConfig;
	import org.mini.events.SiteEventTypes;
	import org.mini.main.Application;
	import org.mini.templates.AbstractPage;
	import org.mini.utils.Singleton;
	
	use namespace mini_internal;

	public class ModuleObject
	{
		static public var weak:Boolean=false;
		
		public var depth:uint;
		
		public var id:String;
		public var src:String;
		public var code:String;
		public var title:String;
		public var preloader:String;
		
		private var _line:String;
		private var _class:Class;
		
		private var _temp:Object;
		private var _params:Object;
		
		private var _assets:Dictionary;
		private var _cache:Dictionary;
		
		private var _loader:ClassLoader;
		private var _instance:*;
		
		private var _isCurrent:Boolean;
		
		public function ModuleObject()
		{
			_isCurrent=false;
			_cache=new Dictionary(weak);
		}
		
		mini_internal function getInstance():*
		{
			return _instance;
		}
		
		mini_internal function set xml(node:XML):void
		{
			_params=XMLUtil.parseAttribute(this,node);
			
			if(!StringUtil.isEmpty(code)) _class=Singleton.getClass(code);
			
			try{
				if(node.asset){
					for each(var asset:XML in node.asset)
					{
						(_assets ||= new Dictionary)[asset.@id]={src:asset.@src,bool:(asset.@nocache=="true")};
					}
				}
				
				if(node.page){
					for each(var page:XML in node.page)
					{
						var obj:ModuleObject=new ModuleObject();
						obj.xml=page;
						(_cache ||= new Dictionary)[page.@id]=obj;
					}
				}
			}
			catch(e:Error){};
		}
		
		mini_internal function set line(str:String):void
		{
			_line=str+id+"/";
			
			if(_class || !StringUtil.isEmpty(src)) SiteStructure.addRouteId(_line,this);
			
			if(_cache){
				for each(var obj:ModuleObject in _cache) obj.line=_line;
			}
		}
		
		mini_internal function set route(str:String):void
		{
			if(str.indexOf(id)==-1) {
				dispose();
				return;
			}
			
			var list:Array=str.split(id);
			var tail:String=list[(list.length-1)];
			_isCurrent=(tail=="/" || StringUtil.isEmpty(tail));

			if(_class && _instance==null){
				_instance=new ClassFactory(_class).newInstance() as AbstractPage;
				_instance.setup(id,assetToLoader(_assets),_params,_isCurrent,(StringUtil.isEmpty(preloader) ? null : Singleton.getClass(preloader)));
				LevelView.getLayer(depth).addChild(_instance);
			}
			else if(_instance==null && !StringUtil.isEmpty(src)){
				_loader=new ClassLoader();
				_loader.addEventListener(Event.COMPLETE,loadCompleteHandler,false,0,true);
				Application.instance.loaderManager.addTask(_loader,AppConfig.swfPath+src);
				_temp=assetToLoader(_assets);
			}
			
			if(_cache){
				for each(var obj:ModuleObject in _cache){
				
					if(obj){
						try{
							obj.route=str;
						}
						catch(e:Error){};
					}
				}
			}
			
			if(_isCurrent) EventDispatcherBase.instance.dispatchEvent(new Event(SiteEventTypes.LAND_UP));
		}
		
		private function loadCompleteHandler(e:Event):void
		{
			_loader.removeEventListener(Event.COMPLETE,loadCompleteHandler);
			_instance=_loader.content;
			_instance.setup(id,_temp,_params,_isCurrent,(StringUtil.isEmpty(preloader) ? null : Singleton.getClass(preloader)));
			LevelView.getLayer(depth).addChild(_instance);
			_temp=null;
		}
		
		private function assetToLoader(dic:Dictionary):Object
		{
			var obj:Object=new Object();
			if(dic==null) return obj;
			
			for(var i:* in dic){
				
				var path:String=AppConfig.swfPath+dic[i].src;
				var loader:ILoader=LoadFileUtil.create(path);
				
				if(loader==null) {
					trace("ModuleObject:assetToLoader",i,"path","("+path+")","is null.");
					continue;
				}
				
				Application.instance.loaderManager.addTask(loader,path+(dic[i].bool ? ("?nocache="+uint(Math.random()*100000)) : ""));
				obj[i]=loader;
			}
				
			return obj;
		}
		
		mini_internal function dispose():void
		{
			if(_instance) {
				
				if(_instance.parent) {
					
					try{
						_instance.parent.removeChild(_instance);
					}
					
					catch(e:Error){};
				}
				
				else _instance.dispose();
				
				_instance=null;
			}
			
			if(_cache){
				for each(var obj:ModuleObject in _cache){
					
					if(obj){
						try{
							obj.dispose();
						}
						catch(e:Error){};
					}
				}
			}
			
			if(_loader){
				_loader.removeEventListener(Event.COMPLETE,loadCompleteHandler);
				_loader=null;
			}
			
			_temp=null;
		}
	}
}